// test_hash.c

#include "sdf.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/sm2.h> 

// 辅助函数：十六进制打印
void print_hex(const char *label, const BYTE *buf, ULONG len) {
    printf("%s (Length: %lu): ", label, (unsigned long)len);
    for (ULONG i = 0; i < len; i++) {
        printf("%02x", buf[i]);
    }
    printf("\n");
}

// =================================================================
// 测试用例 1: 纯 SM3 杂凑
// =================================================================
int test_pure_sm3(HANDLE hDevice) {
    printf("\n--- Test Case 1: Pure SM3 Hash (No SM2 Pre-processing) ---\n");
    LONG ret;
    BYTE hash_result[32];
    ULONG hash_len = 0;
    const char *msg = "The quick brown fox jumps over the lazy dog"; 
    
    // Init: SM2 参数置 NULL/0
    ret = SDF_HashInit(hDevice, SGD_SM3, NULL, NULL, 0);
    if (ret != SDR_OK) { printf("[FAIL] Init Failed! Code: %lX\n", ret); return 0; }
    printf("Init SUCCESS.\n");

    // Update
    ret = SDF_HashUpdate(hDevice, (BYTE *)msg, strlen(msg));
    if (ret != SDR_OK) { printf("[FAIL] Update Failed! Code: %lX\n", ret); return 0; }
    
    // Final
    ret = SDF_HashFinal(hDevice, hash_result, &hash_len);
    if (ret == SDR_OK && hash_len == 32) {
        printf("[PASS] Pure SM3 Hash SUCCESS.\n");
        print_hex("Final Digest", hash_result, hash_len);
        return 1;
    }
    printf("[FAIL] Pure SM3 Hash FAILED. Error Code: %lX\n", ret);
    return 0;
}

// =================================================================
// 测试用例 2: SM2 预处理 (Z_A) + 消息杂凑
// =================================================================
int test_sm2_preprocess(HANDLE hDevice) {
    printf("\n--- Test Case 2: SM2 Pre-processing (Z_A Calculation + Hash M) ---\n");
    LONG ret;
    BYTE hash_result[32];
    ULONG hash_len = 0;
    const char *msg = "message data";
    
    // --- 模拟生成 SM2 公钥和 ID ---
    // --- 模拟生成 SM2 公钥和 ID ---
SM2_KEY temp_key;
if (sm2_key_generate(&temp_key) != 1) { 
    printf("Test Setup Failed: Could not generate SM2 key.\n"); 
    return 0;
}

ECCrefPublicKey pubkey;
pubkey.bits = 256;

// =======================================================
// 最终修复：使用官方函数提取公钥坐标
// =======================================================
uint8_t uncompressed_point[65];

// 1. 将 SM2_KEY 中的 public_key 结构体转换为 65 字节未压缩点数组
if (sm2_z256_point_to_uncompressed_octets(&temp_key.public_key, uncompressed_point) != 1) {
    printf("Test Setup Failed: Could not convert public key to octets.\n");
    return 0;
}

// 2. 提取 X 坐标 (从第 1 字节开始的 32 字节)
// 65字节格式: [0] = 0x04 | [1-32] = X | [33-64] = Y
memcpy(pubkey.x, uncompressed_point + 1, 32); 
// 3. 提取 Y 坐标 (从第 33 字节开始的 32 字节)
memcpy(pubkey.y, uncompressed_point + 33, 32);
// =======================================================



    BYTE id[] = "ALICE123@YAHOO.COM";
    ULONG id_len = strlen((char*)id);

    // 1. Init: 传入 SM2 参数，内部计算 Z_A
    ret = SDF_HashInit(hDevice, SGD_SM3, &pubkey, id, id_len);
    if (ret != SDR_OK) { printf("[FAIL] Init Failed (Z_A)! Code: %lX\n", ret); return 0; }
    printf("Init (Z_A) SUCCESS.\n");

    // 2. Update: 传入消息 M
    ret = SDF_HashUpdate(hDevice, (BYTE *)msg, strlen(msg));
    if (ret != SDR_OK) { printf("[FAIL] Update Failed! Code: %lX\n", ret); return 0; }

    // 3. Final: 输出 Z_A || M 的 SM3 杂凑值 e
    ret = SDF_HashFinal(hDevice, hash_result, &hash_len);
    if (ret == SDR_OK && hash_len == 32) {
        printf("[PASS] SM2 Preprocess + Hash SUCCESS.\n");
        print_hex("e (Z_A || M) Digest", hash_result, hash_len);
        return 1;
    }
    printf("[FAIL] SM2 Preprocess + Hash FAILED. Error Code: %lX\n", ret);
    return 0;
}


int main() {
    HANDLE hDeviceHandle = NULL;
    
    printf("--- Starting SDF Hash Test ---\n");
    
    // 1. 打开设备
    if (SDF_OpenDevice(&hDeviceHandle) != SDR_OK) { 
        printf("[FATAL] SDF_OpenDevice Failed!\n"); 
        return 1; 
    }
    printf("SDF_OpenDevice Successed.\n");
    
    // 运行两个测试用例
    test_pure_sm3(hDeviceHandle);
    test_sm2_preprocess(hDeviceHandle);

    // 2. 关闭设备
    SDF_CloseDevice(hDeviceHandle);
    printf("\nSDF_CloseDevice Successed.\n");
    
    printf("--- SDF Hash Test Finished ---\n");
    return 0;
}
